using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using mesoBoard.Web.Core;
using System.Text.RegularExpressions;
using mesoBoard.Data;
using mesoBoard.Web;
using mesoBoard.Services;
using mesoBoard.Web.Models;
using System.IO;
using Ninject;
using mesoBoard.Data.Repositories;
using System.Xml.Linq;
using System.Data.SqlClient;
using System.Net.Mail;
using System.Net.Sockets;
using System.Configuration;
using System.Web.Configuration;
using System.Net.Configuration;

namespace mesoBoard.Web.Controllers
{
    public class InstallController : Controller
    {

        protected override void ExecuteCore()
        {
            if (bool.Parse(ConfigurationManager.AppSettings["Installed"]))
            {
                View("AlreadyInstalled").ExecuteResult(ControllerContext);
            }
            else
                base.ExecuteCore();
        }
        protected override void Execute(System.Web.Routing.RequestContext requestContext)
        {
            requestContext.HttpContext.Items["mbThemeFolder"] = "Default";

            base.Execute(requestContext);
        }

        public ActionResult Index()
        {
            ViewData["BreadCrumb"] = "Welcome";

            return View();            
        }


        [HttpGet]
        public ActionResult Step1()
        {
            ViewData["StepNumber"] = 1;
            SQLInstallViewModel model = new SQLInstallViewModel
            {
                SQLServerAddress = "localhost",
                SQLUseDefaultCredentials = false,                
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult Step1(SQLInstallViewModel info)
        {
            ViewData["StepNumber"] = 1;

            if (info.SQLUseDefaultCredentials)
            {
                ModelState.Remove("SQLLogin");
                ModelState.Remove("SQLPassword");
            }

            if (ModelState.IsValid)
            {
                SqlConnectionStringBuilder connectionString = new SqlConnectionStringBuilder();
                connectionString.DataSource = info.SQLServerAddress;
                connectionString.InitialCatalog = info.DatabaseName;
                connectionString.MultipleActiveResultSets = true;
                connectionString.IntegratedSecurity = info.SQLUseDefaultCredentials; ;
                if (!info.SQLUseDefaultCredentials)
                {
                    connectionString.UserID = info.SQLLogin;
                    connectionString.Password = info.SQLPassword;
                }

                SqlConnection connection = new SqlConnection(connectionString.ToString());

                try
                {
                    connection.Open();
                    string sql = System.IO.File.ReadAllText(Server.MapPath("~/Install/mesoBoardFresh.sql"));

                    string[] cmds = sql.Split(new string[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);

                    SqlCommand command = new SqlCommand();
                    command.Connection = connection;
                    foreach (string cmd in cmds)
                    {
                        command.CommandText = cmd;
                        command.ExecuteNonQuery();
                    }

                    var configuration = WebConfigurationManager.OpenWebConfiguration("~");

                    configuration.ConnectionStrings.ConnectionStrings["cleanConnectionString"].ConnectionString = connectionString.ToString();
                    configuration.ConnectionStrings.ConnectionStrings["cleanConnectionString"].ProviderName = "System.Data.SqlClient";

                    configuration.ConnectionStrings.ConnectionStrings["mbEntities"].ConnectionString = "metadata=res://*/mbEntities.csdl|res://*/mbEntities.ssdl|res://*/mbEntities.msl;provider=System.Data.SqlClient;provider connection string=\"" + connectionString.ToString()+"\"";
                    configuration.ConnectionStrings.ConnectionStrings["mbEntities"].ProviderName = "System.Data.EntityClient";

                    configuration.Save();

                    connection.Dispose();
                    return RedirectToAction("Step2");
                }
                catch
                {
                    TempData["Notice"] = "Unable to connect to SQL server, check connection information";
                }
                finally
                {
                    connection.Dispose();
                }
                return View(info);
            }
            else
            {
                return View(info);
            }
        }

        [HttpGet]
        public ActionResult Step2()
        {
            ViewData["StepNumber"] = 2;
            ViewData["Success"] = "Successfully connected to database and created tables";

            MailInstallViewModel model = new MailInstallViewModel
            {
                MailServerAddress = "mail." + Request.Url.Host,
                MailUseDefaultCredentials = false,
                PortNumber = 25
            };
            
            return View(model);
        }

        [HttpPost]
        public ActionResult Step2(MailInstallViewModel info)
        {
            ViewData["StepNumber"] = 2;

            if (info.MailUseDefaultCredentials)
            {
                ModelState.Remove("MailLogin");
                ModelState.Remove("MailPassword");
            }

            if (ModelState.IsValid)
            {
                TcpClient client = new TcpClient();
                try
                {
                    client.Connect(info.MailServerAddress, info.PortNumber);
                    client.Close();
                }
                catch (Exception ex)
                {
                    ViewData["Notice"] = "Error connecting to SMTP server, a " + ex.GetType().ToString() + " exception was raised";
                    return View(info);
                }

                var configuration = WebConfigurationManager.OpenWebConfiguration("~");

                MailSettingsSectionGroup settings = (MailSettingsSectionGroup)configuration.GetSectionGroup("system.net/mailSettings");
                SmtpSection smtp = settings.Smtp;
                smtp.From = "no-reply@" + Request.Url.Host;
                smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                smtp.Network.Host = info.MailServerAddress;
                smtp.Network.DefaultCredentials = info.MailUseDefaultCredentials;
                smtp.Network.Port = info.PortNumber;
                smtp.Network.UserName = info.MailLogin;
                smtp.Network.Password = info.MailPassword;
                configuration.Save();

                ConfigRepository configs = new ConfigRepository(new mbEntities(configuration.ConnectionStrings.ConnectionStrings["mbEntities"].ConnectionString));
                configs.UpdateConfig("AutomatedFromEmail", smtp.From);

                TempData["Success"] = "Successfully connected to mail server";
                return RedirectToAction("Step3");
            }
            else
            {
                return View(info);
            }
        }

        [HttpGet]
        public ActionResult Step3()
        {
            ViewData["StepNumber"] = 3;
            return View();
        }

        [HttpPost]
        public ActionResult Step3(string username, string email)
        {
            if (string.IsNullOrWhiteSpace(username))
                ModelState.AddModelError("username", "Enter an admin username");

            if (string.IsNullOrWhiteSpace(username) || !RegEx.IsValidEmail(email))
                ModelState.AddModelError("email", "Enter a valid email address");

            if (ModelState.IsValid)
            {
                string password = Randoms.RandomPassword();

                var configuration = WebConfigurationManager.OpenWebConfiguration("~");
                mbEntities db = new mbEntities(configuration.ConnectionStrings.ConnectionStrings["mbEntities"].ConnectionString);
                RepositoriesWrapper Repositories = new RepositoriesWrapper(db);
                ServicesWrapper mbServices = new ServicesWrapper(Repositories);

                User defaultUser = Repositories.Users.GetUser(1);
                defaultUser.Username = username;
                defaultUser.UsernameLower = username.ToLower();
                Repositories.Users.UpdateUser(defaultUser);

                mbServices.Users.UpdatePassword(1, password);

                defaultUser.Email = email;

                Repositories.Configs.UpdateConfig("BoardURL", Request.Url.Host);

                Repositories.Users.UpdateUser(defaultUser);

                configuration.AppSettings.Settings["Installed"].Value = "true";
                configuration.Save();

                MailSettingsSectionGroup settings = (MailSettingsSectionGroup)configuration.GetSectionGroup("system.net/mailSettings");

                SmtpClient smtp = new SmtpClient();

                try
                {
                    smtp.Send(Repositories.Configs.Value("AutomatedFromEmail"),
                        email,
                        "mesoBoard Installation",
                        "Username: " + username + Environment.NewLine +
                        "Password: " + password);
                }
                catch
                {
                    ViewData["Error"] = "Couldn't send email. Please store the information below for your records";
                }



                ViewData["Username"] = username;
                ViewData["Password"] = password;
                ViewData["Email"] = email;
                ViewData["Success"] = "mesoBoard installation complete";

                try
                {
                    SiteConfig.UpdateCache();
                }
                catch
                {
                    ViewData["Notice"] = "Configuration Cache did not update. Please update manually through the Admin Control Panel";
                }

                return View("InstallationComplete");
            }
            else
            {
                return View();
            }
        }
    }
}
